<template>
  <div style="display: flex;width: 100%;flex:1">

    <div ref='topoRef' :id="domId" style=" flex-grow: 1; overflow:hidden "></div>

    <div class='edit_topo_footer' :style="isFullScreen ? footerFullscreenStyle : {}" v-show="domId === 'editTopo'">
      <ga-button class='mr8' @click="() => emits('on-cancel')">取消</ga-button>
      <ga-button type='primary' class='mr8' @click="emits('on-confirm')">确定</ga-button>
    </div>
    <ga-modal v-model:visible="modalState.visible" title='节点重命名' @ok="onRenameConfirm" @cancel="() => modalState = {
      renameModalVisible: false,
      nameBak: '',
    }" popup-container=".system_topo_warp" destroyOnClose>
      <ga-input :value="modalState.nameBak" @change="(value) => modalState.nameBak = value" />
    </ga-modal>
  </div>

</template>

<script setup>
import G6 from '@antv/g6';
import { watch, onMounted, onUnmounted, ref } from 'vue'
import { Message } from '@garco-design/web-vue';
import { genEditContextMenu, nameTooltip } from './graphPlugins'
import { editTopoInteraction } from './topoInteraction'
import { filter } from 'lodash'
const props = defineProps({
  nowAdjacentNodeId: String,
  domId: String,
  topoData: {
    type: Object,
    default: () => ({ nodes: [], edges: [] })
  },
  systemId: String,
  isFullScreen: Boolean,
  nowAdjacentNodeId: String
})
const emits = defineEmits(['on-cancel', 'on-confirm', 'show-adjacent'])


const modalState = ref({
  visible: false,
  nameBak: '',
  nowRenameNodeId: ''
})

const topoRef = ref()
const graph = ref()
const footerFullscreenStyle = {
  left: 0,
  bottom: 0,
  width: '100%',
}
const draw = () => {
  const { topoData, domId } = props;
  console.log('nodes', topoData,);

  if (!topoData.nodes.length) {
    topoRef.value.innerHTML = '';
    return;
  }
  const { nodes, edges, combos } = topoData;
  const data = { nodes, edges, combos };

  const width = topoRef.value.clientWidth;
  const height = topoRef.value.clientHeight;
  topoRef.value.innerHTML = '';
  const menuHandlers = {
    rename: (node) => {
      console.log(node.id, 'id');

      modalState.value.nowRenameNodeId = node.id
      modalState.value.visible = true
    },
    removeEntrance(node) {
      updateIsEntranceNode(node, 0)
    },
    addEntrance(node) {
      updateIsEntranceNode(node, 1)
    },
    removeSystem(node) {
      updateInSystemNode(node, false)
    },
    addSystem(node) {
      updateInSystemNode(node, true)
    },
    showAdjacentNodes(node) {
      emits('show-adjacent', node)
    }
  }
  const contextMenu = genEditContextMenu(menuHandlers, domId)

  const graphInst = new G6.Graph({
    container: domId,
    width,
    height,
    fitCenter: true,
    autoPaint: false,
    plugins: [nameTooltip, contextMenu],
    modes: {
      default: [
        {
          type: 'zoom-canvas',
          minZoom: 0.5,
          maxZoom: 5
        },
        {
          type: 'drag-node',
          onlyChangeComboSize: true
        },
        'drag-combo',
        'drag-canvas'
      ],
      showComponent: []
    },
    defaultNode: {
      type: 'custom-edit-node'
    },
    defaultEdge: {
      style: {
        endArrow: {
          path: G6.Arrow.triangle(5, 5, 0),
          fill: '#AAAAAA',
        },
        lineWidth: 1,
        stroke: '#AAAAAA',
      },
    },
    layout: {
      type: 'dagre',
      rankdir: 'TB',
      align: 'DL',
      nodesep: 55,
      ranksep: 25,
    },
  });
  graphInst.data(data);
  graphInst.render();

  graph.value = graphInst;

  for (let key in editTopoInteraction) {
    graphInst.on(key, (evt) => {
      const handler = editTopoInteraction[key]
      handler(evt, graph.value)
    })
  }
  graphInst.on("node:click", (evt, graph) => {
    const { item } = evt;
    const targetName = evt.target.get("name");
    const model = item.getModel();
    // 当前点击的不在更多菜单元素时才触发加入和移除系统的逻辑
    if (targetName?.indexOf("node-more") === -1) {
      if (model.inSystem) {
        updateInSystemNode(model, false);
      } else {
        updateInSystemNode(model, true);
      }
    }
  })
  console.log(graphInst, 'graph', graph.value);

  // this.setEdgeLineWidth(graph);
  nowAdjacentNodeCenter();
}
// 当监听到window对象或者container的大小发生变化是，改变画布大小
const changeGraphSize = () => {
  if (graph.value && topoRef.value) {
    const { clientWidth, clientHeight } = topoRef.value;
    graph.value.changeSize(clientWidth, clientHeight);
    // graph.value.fitCenter()
  }
}
// 查看上下游节点时，将当前节点居中
const nowAdjacentNodeCenter = () => {
  const id = props.nowAdjacentNodeId;
  if (id && graph) {
    const item = graph.value.findById(id);
    setTimeout(() => {
      graph.value.focusItem(item);
    })
  }
}

/**
 * 更新是否加入系统
 * @param node 节点信息
 * @param inSystem 是否加入系统 true-加入 false-移除
 * @returns
 */
const updateInSystemNode = (node, inSystem) => {
  const { domId } = props;
  if (!inSystem && domId === 'editTopo') {
    const nodes = graph.value.getNodes().map(item => item.getModel());
    const inSystemNodes = filter(nodes, node => node.inSystem);
    if (inSystemNodes.length <= 1) {
      Message.warning('必须保留一个节点');
      return;
    }
  }
  const item = graph.value.findById(node.id);
  node.inSystem = inSystem;
  graph.value.updateItem(item, node);
  Message.success(`${inSystem ? '加入' : '移除'}系统成功`);
}

/**
 * 更新是否为入口节点
 * @param node 节点信息
 * @param isEntrance 是否为入口节点 1-是 0-不是
 */
const updateIsEntranceNode = (node, isEntrance) => {
  const item = graph.value.findById(node.id);
  node.isEntrance = isEntrance;
  graph.value.updateItem(item, node);
}

// 确认节点重命名
const onRenameConfirm = () => {
  const item = graph.value.findById(modalState.value.nowRenameNodeId);
  console.log(item, 'item rename',modalState.value.nowRenameNodeId);

  const model = item.getModel();
  model.nameBak = modalState.value.nameBak;
  graph.value.updateItem(item, model);
  modalState.value = {
    ...modalState.value,
    visible: false,
    nameBak: ''
  }

}

watch(() => props.topoData, draw)
watch(() => props.isFullScreen, changeGraphSize)
onMounted(() => {
  console.log(props, 'mode');

  draw()
  window.addEventListener('resize', changeGraphSize)
})
onUnmounted(() => {
  window.removeEventListener('resize', changeGraphSize)
})
</script>

<style lang="scss">
.context_menu_list {
  list-style: none;
  margin: 0;
  padding: 0;

  li {
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0 6px;
    line-height: 26px;
    list-style-image: none;
    list-style-type: none;
    cursor: pointer;

    &:hover {
      color: rgb(var(--primary-6));
      background-color: #dcdcdc35;
    }
  }
}
</style>
<style scoped lang="scss">
.edit_topo_footer {
  position: absolute;
  left: -12px;
  bottom: -12px;
  height: 50px;
  width: calc(100% + 12px);
  display: flex;
  justify-content: flex-end;
  align-items: center;
  box-shadow: 0 -2px 3px -1px #00000026;
  background: #FFFFFF;
}
</style>
